home *** CD-ROM | disk | FTP | other *** search
/ PC PowerPlay 58 / pcpp58a.iso / extras / quake 3 source / Q3A_ToolSource.exe / Main / map.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-02  |  26.7 KB  |  1,228 lines

  1. // map.c
  2.  
  3. #include "qbsp.h"
  4.  
  5.  
  6. int            entitySourceBrushes;        // to track editor brush numbers
  7.  
  8. int            numMapPatches;
  9.  
  10. // undefine to make plane finding use linear sort
  11. #define    USE_HASHING
  12. #define    PLANE_HASHES    1024
  13. plane_t        *planehash[PLANE_HASHES];
  14.  
  15. plane_t        mapplanes[MAX_MAP_PLANES];
  16. int            nummapplanes;
  17.  
  18. // as brushes and patches are read in, the shaders are stored out in order
  19. // here, so -onlytextures can just copy them out over the existing shaders
  20. // in the drawSurfaces
  21. char        mapIndexedShaders[MAX_MAP_BRUSHSIDES][MAX_QPATH];
  22. int            numMapIndexedShaders;
  23.  
  24. vec3_t        map_mins, map_maxs;
  25.  
  26. entity_t    *mapent;
  27.  
  28.  
  29.  
  30. int        c_boxbevels;
  31. int        c_edgebevels;
  32.  
  33. int        c_areaportals;
  34. int        c_detail;
  35. int        c_structural;
  36.  
  37. // brushes are parsed into a temporary array of sides,
  38. // which will have the bevels added and duplicates
  39. // removed before the final brush is allocated
  40. bspbrush_t    *buildBrush;
  41.  
  42.  
  43. void TestExpandBrushes (void);
  44. void SetTerrainTextures( void );
  45.  
  46.  
  47. /*
  48. =============================================================================
  49.  
  50. PLANE FINDING
  51.  
  52. =============================================================================
  53. */
  54.  
  55.  
  56. /*
  57. ================
  58. PlaneEqual
  59. ================
  60. */
  61. #define    NORMAL_EPSILON    0.00001
  62. #define    DIST_EPSILON    0.01
  63. qboolean    PlaneEqual (plane_t *p, vec3_t normal, vec_t dist)
  64. {
  65. #if 1
  66.     if (
  67.        fabs(p->normal[0] - normal[0]) < NORMAL_EPSILON
  68.     && fabs(p->normal[1] - normal[1]) < NORMAL_EPSILON
  69.     && fabs(p->normal[2] - normal[2]) < NORMAL_EPSILON
  70.     && fabs(p->dist - dist) < DIST_EPSILON )
  71.         return qtrue;
  72. #else
  73.     if (p->normal[0] == normal[0]
  74.         && p->normal[1] == normal[1]
  75.         && p->normal[2] == normal[2]
  76.         && p->dist == dist)
  77.         return qtrue;
  78. #endif
  79.     return qfalse;
  80. }
  81.  
  82. /*
  83. ================
  84. AddPlaneToHash
  85. ================
  86. */
  87. void    AddPlaneToHash (plane_t *p)
  88. {
  89.     int        hash;
  90.  
  91.     hash = (int)fabs(p->dist) / 8;
  92.     hash &= (PLANE_HASHES-1);
  93.  
  94.     p->hash_chain = planehash[hash];
  95.     planehash[hash] = p;
  96. }
  97.  
  98. /*
  99. ================
  100. CreateNewFloatPlane
  101. ================
  102. */
  103. int CreateNewFloatPlane (vec3_t normal, vec_t dist)
  104. {
  105.     plane_t    *p, temp;
  106.  
  107.     if (VectorLength(normal) < 0.5)
  108.     {
  109.         _printf( "FloatPlane: bad normal\n");
  110.         return -1;
  111.     }
  112.  
  113.     // create a new plane
  114.     if (nummapplanes+2 > MAX_MAP_PLANES)
  115.         Error ("MAX_MAP_PLANES");
  116.  
  117.     p = &mapplanes[nummapplanes];
  118.     VectorCopy (normal, p->normal);
  119.     p->dist = dist;
  120.     p->type = (p+1)->type = PlaneTypeForNormal (p->normal);
  121.  
  122.     VectorSubtract (vec3_origin, normal, (p+1)->normal);
  123.     (p+1)->dist = -dist;
  124.  
  125.     nummapplanes += 2;
  126.  
  127.     // allways put axial planes facing positive first
  128.     if (p->type < 3)
  129.     {
  130.         if (p->normal[0] < 0 || p->normal[1] < 0 || p->normal[2] < 0)
  131.         {
  132.             // flip order
  133.             temp = *p;
  134.             *p = *(p+1);
  135.             *(p+1) = temp;
  136.  
  137.             AddPlaneToHash (p);
  138.             AddPlaneToHash (p+1);
  139.             return nummapplanes - 1;
  140.         }
  141.     }
  142.  
  143.     AddPlaneToHash (p);
  144.     AddPlaneToHash (p+1);
  145.     return nummapplanes - 2;
  146. }
  147.  
  148. /*
  149. ==============
  150. SnapVector
  151. ==============
  152. */
  153. void    SnapVector (vec3_t normal)
  154. {
  155.     int        i;
  156.  
  157.     for (i=0 ; i<3 ; i++)
  158.     {
  159.         if ( fabs(normal[i] - 1) < NORMAL_EPSILON )
  160.         {
  161.             VectorClear (normal);
  162.             normal[i] = 1;
  163.             break;
  164.         }
  165.         if ( fabs(normal[i] - -1) < NORMAL_EPSILON )
  166.         {
  167.             VectorClear (normal);
  168.             normal[i] = -1;
  169.             break;
  170.         }
  171.     }
  172. }
  173.  
  174. /*
  175. ==============
  176. SnapPlane
  177. ==============
  178. */
  179. void    SnapPlane (vec3_t normal, vec_t *dist)
  180. {
  181.     SnapVector (normal);
  182.  
  183.     if (fabs(*dist-Q_rint(*dist)) < DIST_EPSILON)
  184.         *dist = Q_rint(*dist);
  185. }
  186.  
  187. /*
  188. =============
  189. FindFloatPlane
  190.  
  191. =============
  192. */
  193. #ifndef USE_HASHING
  194. int        FindFloatPlane (vec3_t normal, vec_t dist)
  195. {
  196.     int        i;
  197.     plane_t    *p;
  198.  
  199.     SnapPlane (normal, &dist);
  200.     for (i=0, p=mapplanes ; i<nummapplanes ; i++, p++)
  201.     {
  202.         if (PlaneEqual (p, normal, dist))
  203.             return i;
  204.     }
  205.  
  206.     return CreateNewFloatPlane (normal, dist);
  207. }
  208. #else
  209. int        FindFloatPlane (vec3_t normal, vec_t dist)
  210. {
  211.     int        i;
  212.     plane_t    *p;
  213.     int        hash, h;
  214.  
  215.     SnapPlane (normal, &dist);
  216.     hash = (int)fabs(dist) / 8;
  217.     hash &= (PLANE_HASHES-1);
  218.  
  219.     // search the border bins as well
  220.     for (i=-1 ; i<=1 ; i++)
  221.     {
  222.         h = (hash+i)&(PLANE_HASHES-1);
  223.         for (p = planehash[h] ; p ; p=p->hash_chain)
  224.         {
  225.             if (PlaneEqual (p, normal, dist))
  226.                 return p-mapplanes;
  227.         }
  228.     }
  229.  
  230.     return CreateNewFloatPlane (normal, dist);
  231. }
  232. #endif
  233.  
  234. /*
  235. ================
  236. MapPlaneFromPoints
  237. ================
  238. */
  239. int MapPlaneFromPoints (vec3_t p0, vec3_t p1, vec3_t p2) {
  240.     vec3_t    t1, t2, normal;
  241.     vec_t    dist;
  242.  
  243.     VectorSubtract (p0, p1, t1);
  244.     VectorSubtract (p2, p1, t2);
  245.     CrossProduct (t1, t2, normal);
  246.     VectorNormalize (normal, normal);
  247.  
  248.     dist = DotProduct (p0, normal);
  249.  
  250.     return FindFloatPlane (normal, dist);
  251. }
  252.  
  253.  
  254. //====================================================================
  255.  
  256. /*
  257. ===========
  258. SetBrushContents
  259.  
  260. The contents on all sides of a brush should be the same
  261. Sets contentsShader, contents, opaque, and detail
  262. ===========
  263. */
  264. void SetBrushContents( bspbrush_t *b ) {
  265.     int            contents, c2;
  266.     side_t        *s;
  267.     int            i;
  268.     qboolean    mixed;
  269.     int            allFlags;
  270.  
  271.     s = &b->sides[0];
  272.     contents = s->contents;
  273.     b->contentShader = s->shaderInfo;
  274.     mixed = qfalse;
  275.  
  276.     allFlags = 0;
  277.  
  278.     for ( i=1 ; i<b->numsides ; i++, s++ ) {
  279.         s = &b->sides[i];
  280.  
  281.         if ( !s->shaderInfo ) {
  282.             continue;
  283.         }
  284.  
  285.         c2 = s->contents;
  286.         if (c2 != contents) {
  287.             mixed = qtrue;
  288.         }
  289.  
  290.         allFlags |= s->surfaceFlags;
  291.     }
  292.  
  293.     if ( mixed ) {
  294.         qprintf ("Entity %i, Brush %i: mixed face contents\n"
  295.             , b->entitynum, b->brushnum);
  296.     }
  297.  
  298.     if ( ( contents & CONTENTS_DETAIL ) && ( contents & CONTENTS_STRUCTURAL ) ) {
  299.         _printf ("Entity %i, Brush %i: mixed CONTENTS_DETAIL and CONTENTS_STRUCTURAL\n"
  300.             , num_entities-1, entitySourceBrushes );
  301.         contents &= ~CONTENTS_DETAIL;
  302.     }
  303.  
  304.     // the fulldetail flag will cause detail brushes to be
  305.     // treated like normal brushes
  306.     if ( fulldetail ) {
  307.         contents &= ~CONTENTS_DETAIL;
  308.     }
  309.  
  310.     // all translucent brushes that aren't specirically made structural will
  311.     // be detail
  312.     if ( ( contents & CONTENTS_TRANSLUCENT ) && !( contents & CONTENTS_STRUCTURAL ) ) {
  313.         contents |= CONTENTS_DETAIL;
  314.     }
  315.  
  316.     if ( contents & CONTENTS_DETAIL ) {
  317.         c_detail++;
  318.         b->detail = qtrue;
  319.     } else {
  320.         c_structural++;
  321.         b->detail = qfalse;
  322.     }
  323.  
  324.     if ( contents & CONTENTS_TRANSLUCENT ) {
  325.         b->opaque = qfalse;
  326.     } else {
  327.         b->opaque = qtrue;
  328.     }
  329.  
  330.     if ( contents & CONTENTS_AREAPORTAL ) {
  331.         c_areaportals++;
  332.     }
  333.  
  334.     b->contents = contents;
  335. }
  336.  
  337.  
  338. //============================================================================
  339.  
  340. /*
  341. =================
  342. AddBrushBevels
  343.  
  344. Adds any additional planes necessary to allow the brush being
  345. built to be expanded against axial bounding boxes
  346. =================
  347. */
  348. void AddBrushBevels( void ) {
  349.     int        axis, dir;
  350.     int        i, order;
  351.     side_t    sidetemp;
  352.     side_t    *s;
  353.     vec3_t    normal;
  354.     float    dist;
  355.  
  356.     //
  357.     // add the axial planes
  358.     //
  359.     order = 0;
  360.     for (axis=0 ; axis <3 ; axis++)
  361.     {
  362.         for (dir=-1 ; dir <= 1 ; dir+=2, order++)
  363.         {
  364.             // see if the plane is allready present
  365.             for ( i=0, s=buildBrush->sides ; i < buildBrush->numsides ; i++,s++ ) {
  366.                 if (mapplanes[s->planenum].normal[axis] == dir)
  367.                     break;
  368.             }
  369.  
  370.             if (i == buildBrush->numsides )
  371.             {    // add a new side
  372.                 if ( buildBrush->numsides == MAX_BUILD_SIDES ) {
  373.                     Error( "MAX_BUILD_SIDES" );
  374.                 }
  375.                 memset( s, 0, sizeof( *s ) );
  376.                 buildBrush->numsides++;
  377.                 VectorClear (normal);
  378.                 normal[axis] = dir;
  379.                 if (dir == 1)
  380.                     dist = buildBrush->maxs[axis];
  381.                 else
  382.                     dist = -buildBrush->mins[axis];
  383.                 s->planenum = FindFloatPlane (normal, dist);
  384.                 s->contents = buildBrush->sides[0].contents;
  385.                 s->bevel = qtrue;
  386.                 c_boxbevels++;
  387.             }
  388.  
  389.             // if the plane is not in it canonical order, swap it
  390.             if (i != order)
  391.             {
  392.                 sidetemp = buildBrush->sides[order];
  393.                 buildBrush->sides[order] = buildBrush->sides[i];
  394.                 buildBrush->sides[i] = sidetemp;
  395.             }
  396.         }
  397.     }
  398.  
  399.     //
  400.     // add the edge bevels
  401.     //
  402.     if ( buildBrush->numsides == 6 ) {
  403.         return;        // pure axial
  404.   } else {
  405.       int            j, k, l;
  406.       float        d;
  407.       winding_t    *w, *w2;
  408.       side_t        *s2;
  409.       vec3_t        vec, vec2;
  410.  
  411.       // test the non-axial plane edges
  412.       // this code tends to cause some problems...
  413.       for (i=6 ; i<buildBrush->numsides ; i++)
  414.       {
  415.           s = buildBrush->sides + i;
  416.           w = s->winding;
  417.           if (!w)
  418.               continue;
  419.           for (j=0 ; j<w->numpoints ; j++)
  420.           {
  421.               k = (j+1)%w->numpoints;
  422.               VectorSubtract (w->p[j], w->p[k], vec);
  423.               if (VectorNormalize (vec, vec) < 0.5)
  424.                   continue;
  425.               SnapVector (vec);
  426.               for (k=0 ; k<3 ; k++)
  427.                   if ( vec[k] == -1 || vec[k] == 1)
  428.                       break;    // axial
  429.               if (k != 3)
  430.                   continue;    // only test non-axial edges
  431.  
  432.               // try the six possible slanted axials from this edge
  433.               for (axis=0 ; axis <3 ; axis++)
  434.               {
  435.                   for (dir=-1 ; dir <= 1 ; dir+=2)
  436.                   {
  437.                       // construct a plane
  438.                       VectorClear (vec2);
  439.                       vec2[axis] = dir;
  440.                       CrossProduct (vec, vec2, normal);
  441.                       if (VectorNormalize (normal, normal) < 0.5)
  442.                           continue;
  443.                       dist = DotProduct (w->p[j], normal);
  444.  
  445.                       // if all the points on all the sides are
  446.                       // behind this plane, it is a proper edge bevel
  447.                       for (k=0 ; k < buildBrush->numsides ; k++)
  448.                       {
  449.                           // if this plane has allready been used, skip it
  450.                           if (PlaneEqual (&mapplanes[buildBrush->sides[k].planenum]
  451.                               , normal, dist) )
  452.                               break;
  453.  
  454.                           w2 = buildBrush->sides[k].winding;
  455.                           if (!w2)
  456.                               continue;
  457.                           for (l=0 ; l<w2->numpoints ; l++)
  458.                           {
  459.                               d = DotProduct (w2->p[l], normal) - dist;
  460.                               if (d > 0.1)
  461.                                   break;    // point in front
  462.                           }
  463.                           if (l != w2->numpoints)
  464.                               break;
  465.                       }
  466.  
  467.                       if (k != buildBrush->numsides)
  468.                           continue;    // wasn't part of the outer hull
  469.                       // add this plane
  470.                       if ( buildBrush->numsides == MAX_BUILD_SIDES ) {
  471.                           Error( "MAX_BUILD_SIDES" );
  472.                       }
  473.  
  474.                       s2 = &buildBrush->sides[buildBrush->numsides];
  475.                       buildBrush->numsides++;
  476.                       memset( s2, 0, sizeof( *s2 ) );
  477.  
  478.                       s2->planenum = FindFloatPlane (normal, dist);
  479.                       s2->contents = buildBrush->sides[0].contents;
  480.                       s2->bevel = qtrue;
  481.                       c_edgebevels++;
  482.                   }
  483.               }
  484.           }
  485.       }
  486.   }
  487. }
  488.  
  489. /*
  490. ===============
  491. AddBackSides
  492.  
  493. fog volumes need to have inside faces created
  494. ===============
  495. */
  496. void AddBackSides( void ) {
  497. /*
  498.     bspbrush_t    *b;
  499.     int            i, originalSides;
  500.     side_t        *s;
  501.     side_t        *newSide;
  502.  
  503.     b = buildBrush;
  504.     originalSides = b->numsides;
  505.     for ( i = 0 ; i < originalSides ; i++ ) {
  506.         s = &b->sides[i];
  507.         if ( !s->shaderInfo ) {
  508.             continue;
  509.         }
  510.         if ( !(s->shaderInfo->contents & CONTENTS_FOG) ) {
  511.             continue;
  512.         }
  513.  
  514.         // duplicate the up-facing side
  515.         if ( mapplanes[ s->planenum ].normal[2] == 1 ) {
  516.             newSide = &b->sides[ b->numsides ];
  517.             b->numsides++;
  518.  
  519.             *newSide = *s;
  520.             newSide->backSide = qtrue;
  521.             newSide->planenum = s->planenum ^ 1;    // opposite side
  522.         }
  523.     }
  524. */
  525. }
  526.  
  527. /*
  528. ===============
  529. FinishBrush
  530.  
  531. Produces a final brush based on the buildBrush->sides array
  532. and links it to the current entity
  533. ===============
  534. */
  535. bspbrush_t *FinishBrush( void ) {
  536.     bspbrush_t    *b;
  537.  
  538.     // liquids may need to have extra sides created for back sides
  539.     AddBackSides();
  540.  
  541.     // create windings for sides and bounds for brush
  542.     if ( !CreateBrushWindings( buildBrush ) ) {
  543.         // don't keep this brush
  544.         return NULL;
  545.     }
  546.  
  547.     // brushes that will not be visible at all are forced to be detail
  548.     if ( buildBrush->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) )
  549.     {
  550.         buildBrush->detail = qtrue;
  551.         c_detail++;
  552.     }
  553.  
  554.     //
  555.     // origin brushes are removed, but they set
  556.     // the rotation origin for the rest of the brushes
  557.     // in the entity.  After the entire entity is parsed,
  558.     // the planenums and texinfos will be adjusted for
  559.     // the origin brush
  560.     //
  561.     if ( buildBrush->contents & CONTENTS_ORIGIN )
  562.     {
  563.         char    string[32];
  564.         vec3_t    origin;
  565.  
  566.         if (num_entities == 1) {
  567.             _printf ("Entity %i, Brush %i: origin brushes not allowed in world\n"
  568.                 ,  num_entities - 1, entitySourceBrushes);
  569.             return NULL;
  570.         }
  571.  
  572.         VectorAdd (buildBrush->mins, buildBrush->maxs, origin);
  573.         VectorScale (origin, 0.5, origin);
  574.  
  575.         sprintf (string, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
  576.         SetKeyValue (&entities[num_entities - 1], "origin", string);
  577.  
  578.         VectorCopy (origin, entities[num_entities - 1].origin);
  579.  
  580.         // don't keep this brush
  581.         return NULL;
  582.     }
  583.  
  584.     if ( buildBrush->contents & CONTENTS_AREAPORTAL ) {
  585.         if (num_entities != 1) {
  586.             _printf ("Entity %i, Brush %i: areaportals only allowed in world\n"
  587.                 ,  num_entities - 1, entitySourceBrushes);
  588.             return NULL;
  589.         }
  590.     }
  591.  
  592.     AddBrushBevels ();
  593.  
  594.     // keep it
  595.     b = CopyBrush( buildBrush );
  596.  
  597.     b->entitynum = num_entities-1;
  598.     b->brushnum = entitySourceBrushes;
  599.  
  600.     b->original = b;
  601.  
  602.     b->next = mapent->brushes;
  603.     mapent->brushes = b;
  604.  
  605.     return b;
  606. }
  607.  
  608. //======================================================================
  609.  
  610.  
  611. /*
  612. ==================
  613. textureAxisFromPlane
  614. ==================
  615. */
  616. vec3_t    baseaxis[18] =
  617. {
  618. {0,0,1}, {1,0,0}, {0,-1,0},            // floor
  619. {0,0,-1}, {1,0,0}, {0,-1,0},        // ceiling
  620. {1,0,0}, {0,1,0}, {0,0,-1},            // west wall
  621. {-1,0,0}, {0,1,0}, {0,0,-1},        // east wall
  622. {0,1,0}, {1,0,0}, {0,0,-1},            // south wall
  623. {0,-1,0}, {1,0,0}, {0,0,-1}            // north wall
  624. };
  625.  
  626. void TextureAxisFromPlane(plane_t *pln, vec3_t xv, vec3_t yv)
  627. {
  628.     int        bestaxis;
  629.     vec_t    dot,best;
  630.     int        i;
  631.     
  632.     best = 0;
  633.     bestaxis = 0;
  634.     
  635.     for (i=0 ; i<6 ; i++)
  636.     {
  637.         dot = DotProduct (pln->normal, baseaxis[i*3]);
  638.         if (dot > best)
  639.         {
  640.             best = dot;
  641.             bestaxis = i;
  642.         }
  643.     }
  644.     
  645.     VectorCopy (baseaxis[bestaxis*3+1], xv);
  646.     VectorCopy (baseaxis[bestaxis*3+2], yv);
  647. }
  648.  
  649.  
  650.  
  651. /*
  652. =================
  653. QuakeTextureVecs
  654.  
  655. Creates world-to-texture mapping vecs for crappy quake plane arrangements
  656. =================
  657. */
  658. void QuakeTextureVecs(     plane_t *plane, vec_t shift[2], vec_t rotate, vec_t scale[2],
  659.                       vec_t mappingVecs[2][4] ) {
  660.  
  661.     vec3_t    vecs[2];
  662.     int        sv, tv;
  663.     vec_t    ang, sinv, cosv;
  664.     vec_t    ns, nt;
  665.     int        i, j;
  666.  
  667.     TextureAxisFromPlane(plane, vecs[0], vecs[1]);
  668.  
  669.     if (!scale[0])
  670.         scale[0] = 1;
  671.     if (!scale[1])
  672.         scale[1] = 1;
  673.  
  674.     // rotate axis
  675.     if (rotate == 0)
  676.         { sinv = 0 ; cosv = 1; }
  677.     else if (rotate == 90)
  678.         { sinv = 1 ; cosv = 0; }
  679.     else if (rotate == 180)
  680.         { sinv = 0 ; cosv = -1; }
  681.     else if (rotate == 270)
  682.         { sinv = -1 ; cosv = 0; }
  683.     else
  684.     {    
  685.         ang = rotate / 180 * Q_PI;
  686.         sinv = sin(ang);
  687.         cosv = cos(ang);
  688.     }
  689.  
  690.     if (vecs[0][0])
  691.         sv = 0;
  692.     else if (vecs[0][1])
  693.         sv = 1;
  694.     else
  695.         sv = 2;
  696.                 
  697.     if (vecs[1][0])
  698.         tv = 0;
  699.     else if (vecs[1][1])
  700.         tv = 1;
  701.     else
  702.         tv = 2;
  703.                     
  704.     for (i=0 ; i<2 ; i++) {
  705.         ns = cosv * vecs[i][sv] - sinv * vecs[i][tv];
  706.         nt = sinv * vecs[i][sv] +  cosv * vecs[i][tv];
  707.         vecs[i][sv] = ns;
  708.         vecs[i][tv] = nt;
  709.     }
  710.  
  711.     for (i=0 ; i<2 ; i++)
  712.         for (j=0 ; j<3 ; j++)
  713.             mappingVecs[i][j] = vecs[i][j] / scale[i];
  714.  
  715.     mappingVecs[0][3] = shift[0];
  716.     mappingVecs[1][3] = shift[1];
  717. }
  718.  
  719. //======================================================================
  720.  
  721. /*
  722. =================
  723. ParseRawBrush
  724.  
  725. Just parses the sides into buildBrush->sides[], nothing else.
  726. no validation, back plane removal, etc.
  727.  
  728. Timo - 08/26/99
  729. added brush epairs parsing ( ignoring actually )
  730. Timo - 08/04/99
  731. added exclusive brush primitive parsing
  732. Timo - 08/08/99
  733. support for old brush format back in
  734. NOTE : it would be "cleaner" to have seperate functions to parse between old and new brushes
  735. =================
  736. */
  737. void    ParseRawBrush( ) {
  738.     side_t        *side;
  739.     vec3_t        planepts[3];
  740.     int            planenum;
  741.     shaderInfo_t    *si;
  742.     // old brushes
  743.     vec_t        shift[2];
  744.     vec_t        rotate;
  745.     vec_t        scale[2];
  746.     char        name[MAX_QPATH];
  747.     char        shader[MAX_QPATH];
  748.     int            flags;
  749.  
  750.     buildBrush->numsides = 0;
  751.     buildBrush->detail = qfalse;
  752.  
  753.     if (g_bBrushPrimit==BPRIMIT_NEWBRUSHES)
  754.         MatchToken( "{" );
  755.  
  756.     do
  757.     {
  758.         if (!GetToken (qtrue))
  759.             break;
  760.         if (!strcmp (token, "}") )
  761.             break;
  762.         //Timo : brush primitive : here we may have to jump over brush epairs ( only used in editor )
  763.         if (g_bBrushPrimit==BPRIMIT_NEWBRUSHES)
  764.         {
  765.             do
  766.             {
  767.                 if (strcmp (token, "(") )
  768.                     GetToken( qfalse );
  769.                 else
  770.                     break;
  771.                 GetToken( qtrue );
  772.             } while (1);
  773.         }
  774.         UnGetToken();
  775.  
  776.         if ( buildBrush->numsides == MAX_BUILD_SIDES ) {
  777.             Error( "MAX_BUILD_SIDES" );
  778.         }
  779.  
  780.         side = &buildBrush->sides[ buildBrush->numsides ];
  781.         memset( side, 0, sizeof( *side ) );
  782.         buildBrush->numsides++;
  783.  
  784.         // read the three point plane definition
  785.         Parse1DMatrix( 3, planepts[0] );
  786.         Parse1DMatrix( 3, planepts[1] );
  787.         Parse1DMatrix( 3, planepts[2] );
  788.  
  789.         if (g_bBrushPrimit==BPRIMIT_NEWBRUSHES)
  790.             // read the texture matrix
  791.             Parse2DMatrix( 2, 3, (float *)side->texMat );
  792.  
  793.         // read the texturedef
  794.         GetToken (qfalse);
  795.         strcpy (name, token);
  796.  
  797.         // save the shader name for retexturing
  798.         if ( numMapIndexedShaders == MAX_MAP_BRUSHSIDES ) {
  799.             Error( "MAX_MAP_BRUSHSIDES" );
  800.         }
  801.         strcpy( mapIndexedShaders[numMapIndexedShaders], name );
  802.         numMapIndexedShaders++;
  803.  
  804.         if (g_bBrushPrimit==BPRIMIT_OLDBRUSHES)
  805.         {
  806.             GetToken (qfalse);
  807.             shift[0] = atoi(token);
  808.             GetToken (qfalse);
  809.             shift[1] = atoi(token);
  810.             GetToken (qfalse);
  811.             rotate = atoi(token);    
  812.             GetToken (qfalse);
  813.             scale[0] = atof(token);
  814.             GetToken (qfalse);
  815.             scale[1] = atof(token);
  816.         }
  817.  
  818.         // find default flags and values
  819.         sprintf( shader, "textures/%s", name );
  820.         si = ShaderInfoForShader( shader );
  821.         side->shaderInfo = si;
  822.         side->surfaceFlags = si->surfaceFlags;
  823.         side->value = si->value;
  824.         side->contents = si->contents;
  825.  
  826.         // allow override of default flags and values
  827.         // in Q3, the only thing you can override is DETAIL
  828.         if (TokenAvailable())
  829.         {
  830.             GetToken (qfalse);
  831. //            side->contents = atoi(token);
  832.             flags = atoi(token);
  833.             if ( flags & CONTENTS_DETAIL ) {
  834.                 side->contents |= CONTENTS_DETAIL;
  835.             }
  836.  
  837.             GetToken (qfalse);
  838. //            td.flags = atoi(token);
  839.  
  840.             GetToken (qfalse);
  841. //            td.value = atoi(token);
  842.         }
  843.  
  844.  
  845.         // find the plane number
  846.         planenum = MapPlaneFromPoints (planepts[0], planepts[1], planepts[2]);
  847.         side->planenum = planenum;
  848.  
  849.         if (g_bBrushPrimit==BPRIMIT_OLDBRUSHES)
  850.             // get the texture mapping for this texturedef / plane combination
  851.             QuakeTextureVecs( &mapplanes[planenum], shift, rotate, scale, side->vecs );
  852.  
  853.     } while (1);
  854.  
  855.     if (g_bBrushPrimit==BPRIMIT_NEWBRUSHES)
  856.     {
  857.         UnGetToken();
  858.         MatchToken( "}" );
  859.         MatchToken( "}" );
  860.     }
  861. }
  862.  
  863. /*
  864. =================
  865. RemoveDuplicateBrushPlanes
  866.  
  867. Returns false if the brush has a mirrored set of planes,
  868. meaning it encloses no volume.
  869. Also removes planes without any normal
  870. =================
  871. */
  872. qboolean RemoveDuplicateBrushPlanes( bspbrush_t * b ) {
  873.     int            i, j, k;
  874.     side_t        *sides;
  875.  
  876.     sides = b->sides;
  877.  
  878.     for ( i = 1 ; i < b->numsides ; i++ ) {
  879.  
  880.         // check for a degenerate plane
  881.         if ( sides[i].planenum == -1) {
  882.             _printf ("Entity %i, Brush %i: degenerate plane\n"
  883.                 , b->entitynum, b->brushnum);
  884.             // remove it
  885.             for ( k = i + 1 ; k < b->numsides ; k++ ) {
  886.                 sides[k-1] = sides[k];
  887.             }
  888.             b->numsides--;
  889.             i--;
  890.             continue;
  891.         }
  892.  
  893.         // check for duplication and mirroring
  894.         for ( j = 0 ; j < i ; j++ ) {
  895.             if ( sides[i].planenum == sides[j].planenum ) {
  896.                 _printf ("Entity %i, Brush %i: duplicate plane\n"
  897.                     , b->entitynum, b->brushnum);
  898.                 // remove the second duplicate
  899.                 for ( k = i + 1 ; k < b->numsides ; k++ ) {
  900.                     sides[k-1] = sides[k];
  901.                 }
  902.                 b->numsides--;
  903.                 i--;
  904.                 break;
  905.             }
  906.  
  907.             if ( sides[i].planenum == (sides[j].planenum ^ 1) ) {
  908.                 // mirror plane, brush is invalid
  909.                 _printf ("Entity %i, Brush %i: mirrored plane\n"
  910.                     , b->entitynum, b->brushnum);
  911.                 return qfalse;
  912.             }
  913.         }
  914.     }
  915.     return qtrue;
  916. }
  917.  
  918.  
  919. /*
  920. =================
  921. ParseBrush
  922.  
  923.   qboolean parameter to true -> parse new brush primitive format ( else use old format )
  924. =================
  925. */
  926. void ParseBrush (void) {
  927.     bspbrush_t    *b;
  928.  
  929.     ParseRawBrush();
  930.  
  931.     buildBrush->portalareas[0] = -1;
  932.     buildBrush->portalareas[1] = -1;
  933.     buildBrush->entitynum = num_entities-1;
  934.     buildBrush->brushnum = entitySourceBrushes;
  935.  
  936.     // if there are mirrored planes, the entire brush is invalid
  937.     if ( !RemoveDuplicateBrushPlanes( buildBrush ) ) {
  938.         return;
  939.     }
  940.  
  941.     // get the content for the entire brush
  942.     SetBrushContents( buildBrush );
  943.  
  944.     // allow detail brushes to be removed 
  945.     if (nodetail && (buildBrush->contents & CONTENTS_DETAIL) ) {
  946.         FreeBrush( buildBrush );
  947.         return;
  948.     }
  949.  
  950.     // allow water brushes to be removed
  951.     if (nowater && (buildBrush->contents & (CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_WATER)) ) {
  952.         FreeBrush( buildBrush );
  953.         return;
  954.     }
  955.  
  956.     b = FinishBrush( );
  957.     if ( !b ) {
  958.         return;
  959.     }
  960. }
  961.  
  962.  
  963. /*
  964. ================
  965. MoveBrushesToWorld
  966.  
  967. Takes all of the brushes from the current entity and
  968. adds them to the world's brush list.
  969.  
  970. Used by func_group
  971. ================
  972. */
  973. void MoveBrushesToWorld (entity_t *mapent) {
  974.     bspbrush_t    *b, *next;
  975.     parseMesh_t    *pm;
  976.  
  977.     // move brushes
  978.     for ( b = mapent->brushes ; b ; b = next ) {
  979.         next = b->next;
  980.  
  981.         b->next = entities[0].brushes;
  982.         entities[0].brushes = b;
  983.     }
  984.     mapent->brushes = NULL;
  985.  
  986.     // move patches
  987.     if ( mapent->patches ) {
  988.  
  989.         for ( pm = mapent->patches ; pm->next ; pm = pm->next ) {
  990.         }
  991.  
  992.         pm->next = entities[0].patches;
  993.         entities[0].patches = mapent->patches;
  994.  
  995.         mapent->patches = NULL;
  996.     }
  997. }
  998.  
  999.  
  1000. /*
  1001. ================
  1002. AdjustBrushesForOrigin
  1003. ================
  1004. */
  1005. void AdjustBrushesForOrigin( entity_t *ent ) {
  1006.     bspbrush_t    *b;
  1007.     int            i;
  1008.     side_t        *s;
  1009.     vec_t        newdist;
  1010.     parseMesh_t    *p;
  1011.  
  1012.     for ( b = ent->brushes ; b ; b = b->next ) {
  1013.         for (i=0 ; i<b->numsides ; i++) {
  1014.             s = &b->sides[i];
  1015.             newdist = mapplanes[s->planenum].dist -
  1016.                 DotProduct (mapplanes[s->planenum].normal, ent->origin);
  1017.             s->planenum = FindFloatPlane (mapplanes[s->planenum].normal, newdist);
  1018.         }
  1019.         CreateBrushWindings(b);
  1020.     }
  1021.  
  1022.     for ( p = ent->patches ; p ; p = p->next ) {
  1023.         for ( i = 0 ; i < p->mesh.width*p->mesh.height ; i++ ) {
  1024.             VectorSubtract( p->mesh.verts[i].xyz, ent->origin, p->mesh.verts[i].xyz );
  1025.         }
  1026.     }
  1027.  
  1028. }
  1029.  
  1030. /*
  1031. ================
  1032. ParseMapEntity
  1033. ================
  1034. */
  1035. qboolean    ParseMapEntity (void) {
  1036.     epair_t        *e;
  1037.  
  1038.     if (!GetToken (qtrue))
  1039.         return qfalse;
  1040.  
  1041.     if (strcmp (token, "{") )
  1042.     {
  1043.         Error ("ParseEntity: { not found, found %s on line %d - last entity was at: <%4.2f, %4.2f, %4.2f>...", token, scriptline, entities[num_entities].origin[0], entities[num_entities].origin[1], entities[num_entities].origin[2]);
  1044.     }
  1045.     
  1046.     if (num_entities == MAX_MAP_ENTITIES)
  1047.         Error ("num_entities == MAX_MAP_ENTITIES");
  1048.  
  1049.     entitySourceBrushes = 0;
  1050.  
  1051.     mapent = &entities[num_entities];
  1052.     num_entities++;
  1053.     memset (mapent, 0, sizeof(*mapent));
  1054.  
  1055.     do
  1056.     {
  1057.         if (!GetToken (qtrue))
  1058.             Error ("ParseEntity: EOF without closing brace");
  1059.         if (!strcmp (token, "}") )
  1060.             break;
  1061.  
  1062.         if (!strcmp (token, "{") ) {
  1063.             // parse a brush or patch
  1064.             if (!GetToken (qtrue))
  1065.                 break;
  1066.             if ( !strcmp( token, "patchDef2" ) ) {
  1067.                 numMapPatches++;
  1068.                 ParsePatch();
  1069.             } else if ( !strcmp( token, "brushDef" ) ) {
  1070.                 if (g_bBrushPrimit==BPRIMIT_OLDBRUSHES)
  1071.                     Error("old brush format not allowed in new brush format map");
  1072.                 g_bBrushPrimit=BPRIMIT_NEWBRUSHES;
  1073.                 // parse brush primitive
  1074.                 ParseBrush();
  1075.             }
  1076.             else
  1077.             {
  1078.                 if (g_bBrushPrimit==BPRIMIT_NEWBRUSHES)
  1079.                     Error("new brush format not allowed in old brush format map");
  1080.                 g_bBrushPrimit=BPRIMIT_OLDBRUSHES;
  1081.                 // parse old brush format
  1082.                 UnGetToken();
  1083.                 ParseBrush();
  1084.             }
  1085.             entitySourceBrushes++;
  1086.         }
  1087.         else
  1088.         {
  1089.             // parse a key / value pair
  1090.             e = ParseEpair ();
  1091.             e->next = mapent->epairs;
  1092.             mapent->epairs = e;
  1093.         }
  1094.     } while (1);
  1095.  
  1096.     GetVectorForKey (mapent, "origin", mapent->origin);
  1097.  
  1098.     //
  1099.     // if there was an origin brush, offset all of the planes and texinfo
  1100.     // for all the brushes in the entity
  1101.     if (mapent->origin[0] || mapent->origin[1] || mapent->origin[2]) {
  1102.         AdjustBrushesForOrigin( mapent );
  1103.     }
  1104.  
  1105.   // group_info entities are just for editor grouping
  1106.   // ignored
  1107.   // FIXME: leak!
  1108.   if (!strcmp("group_info", ValueForKey (mapent, "classname")))
  1109.   {
  1110.     num_entities--;
  1111.     return qtrue;
  1112.   }
  1113.  
  1114.     // group entities are just for editor convenience
  1115.     // toss all brushes into the world entity
  1116.     if (!strcmp ("func_group", ValueForKey (mapent, "classname")))
  1117.     {
  1118.         if ( !strcmp ("1", ValueForKey (mapent, "terrain"))) {
  1119.             SetTerrainTextures();
  1120.         }
  1121.         MoveBrushesToWorld (mapent);
  1122.         num_entities--;
  1123.         return qtrue;
  1124.     }
  1125.  
  1126.     return qtrue;
  1127. }
  1128.  
  1129. //===================================================================
  1130.  
  1131.  
  1132. /*
  1133. ================
  1134. LoadMapFile
  1135. ================
  1136. */
  1137. void LoadMapFile (char *filename) {        
  1138.     bspbrush_t    *b;
  1139.  
  1140.     qprintf ("--- LoadMapFile ---\n");
  1141.     _printf ("Loading map file %s\n", filename);
  1142.  
  1143.     LoadScriptFile (filename);
  1144.  
  1145.     num_entities = 0;
  1146.     numMapDrawSurfs = 0;
  1147.     c_detail = 0;
  1148.  
  1149.     g_bBrushPrimit = BPRIMIT_UNDEFINED;
  1150.  
  1151.     // allocate a very large temporary brush for building
  1152.     // the brushes as they are loaded
  1153.     buildBrush = AllocBrush( MAX_BUILD_SIDES );
  1154.  
  1155.     while (ParseMapEntity ())
  1156.     {
  1157.     }
  1158.  
  1159.     ClearBounds (map_mins, map_maxs);
  1160.     for ( b = entities[0].brushes ; b ; b=b->next ) {
  1161.         AddPointToBounds( b->mins, map_mins, map_maxs );
  1162.         AddPointToBounds( b->maxs, map_mins, map_maxs );
  1163.     }
  1164.  
  1165.     qprintf ("%5i total world brushes\n", CountBrushList( entities[0].brushes ) );
  1166.     qprintf ("%5i detail brushes\n", c_detail );
  1167.     qprintf ("%5i patches\n", numMapPatches);
  1168.     qprintf ("%5i boxbevels\n", c_boxbevels);
  1169.     qprintf ("%5i edgebevels\n", c_edgebevels);
  1170.     qprintf ("%5i entities\n", num_entities);
  1171.     qprintf ("%5i planes\n", nummapplanes);
  1172.     qprintf ("%5i areaportals\n", c_areaportals);
  1173.     qprintf ("size: %5.0f,%5.0f,%5.0f to %5.0f,%5.0f,%5.0f\n", map_mins[0],map_mins[1],map_mins[2],
  1174.         map_maxs[0],map_maxs[1],map_maxs[2]);
  1175.  
  1176.     if ( fakemap ) {
  1177.         WriteBspBrushMap ("fakemap.map", entities[0].brushes );
  1178.     }
  1179.  
  1180.     if ( testExpand ) {
  1181.         TestExpandBrushes ();
  1182.     }
  1183. }
  1184.  
  1185.  
  1186. //====================================================================
  1187.  
  1188.  
  1189. /*
  1190. ================
  1191. TestExpandBrushes
  1192.  
  1193. Expands all the brush planes and saves a new map out to
  1194. allow visual inspection of the clipping bevels
  1195. ================
  1196. */
  1197. void TestExpandBrushes( void ) {
  1198.     side_t    *s;
  1199.     int        i, j;
  1200.     bspbrush_t    *brush, *list, *copy;
  1201.     vec_t    dist;
  1202.     plane_t        *plane;
  1203.  
  1204.     list = NULL;
  1205.  
  1206.     for ( brush = entities[0].brushes ; brush ; brush = brush->next ) {
  1207.         copy = CopyBrush( brush );
  1208.         copy->next = list;
  1209.         list = copy;
  1210.  
  1211.         // expand all the planes
  1212.         for ( i=0 ; i<brush->numsides ; i++ ) {
  1213.             s = brush->sides + i;
  1214.             plane = &mapplanes[s->planenum];
  1215.             dist = plane->dist;
  1216.             for (j=0 ; j<3 ; j++) {
  1217.                 dist += fabs( 16 * plane->normal[j] );
  1218.             }
  1219.             s->planenum = FindFloatPlane( plane->normal, dist );
  1220.         }
  1221.  
  1222.     }
  1223.  
  1224.     WriteBspBrushMap ( "expanded.map", entities[0].brushes );
  1225.  
  1226.     Error ("can't proceed after expanding brushes");
  1227. }
  1228.